package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.model.sdo.AllocateOrderDetailMessageSDO;
import com.alibaba.cirtus.ots.application.adapter.ability.model.sdo.AllocateOrderDetailUpdateSDO;
import com.alibaba.cirtus.ots.application.adapter.ability.model.sdo.AllocateOrderMessageSDO;
import com.alibaba.cirtus.ots.application.adapter.ability.model.sdo.AllocateOrderWithOrderDetailsMessageSDO;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.otsapplicationadaptersdk.mnsapif037v2.dto.AutoRetryRequest;
import com.epoch.app.otsapplicationadaptersdk.mnsapif037v2.dto.CallbackRequest;
import com.epoch.app.otsapplicationadaptersdk.mnsapif037v2.dto.HandleRequest;
import com.epoch.app.otsapplicationadaptersdk.mnsapif037v2.service.MnSapIf037V2Service;
import com.epoch.app.otsapplicationadaptersdk.model.dto.RestSapAllocateOrderModifyRequest;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetryLoadListRequest;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.sapretry.dto.DeleteRequest;
import com.epoch.app.otsapplicationadaptersdk.sapretry.dto.DeleteResponse;
import com.epoch.app.otsapplicationadaptersdk.sapretry.dto.UpdateResponse;
import com.epoch.app.otsapplicationadaptersdk.sapretry.model.SapRetry;
import com.epoch.app.otsapplicationadaptersdk.sapretry.service.SapRetryService;
import com.epoch.app.otsapplicationadaptersdk.service.SapService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author mingyang
 * @since 2024/01/22
 */
@Component
@Primary
public class MnSapIf037V2ServiceImpl implements MnSapIf037V2Service {

    private final Log log = Log.getLogger(MnSapIf037V2ServiceImpl.class);

    private static final String pattern = "yyyyMMddHHmmss";

    private static final String API_CODE = "MnSapIf037V2$handle";

    @Resource
    private SapService sapService;

    @Resource
    private SapRetryService sapRetryService;

    @Override
    @ProcessInvoker(remark = "MnSapIf037V2Service", errorCode = "OTS-02-007-00-16-999")
    public Object handle(HandleRequest handleRequest) {
        log.info("MnSapIf037V2Service_doHandler,request:{}", JSON.toJSONString(handleRequest));
        AllocateOrderWithOrderDetailsMessageSDO messageSDO = JSON.parseObject(handleRequest.getMessage(), AllocateOrderWithOrderDetailsMessageSDO.class);

        AllocateOrderMessageSDO allocateOrderSDO = messageSDO.getAllocateOrderSDO();
        RestSapAllocateOrderModifyRequest request = new RestSapAllocateOrderModifyRequest();
        request.setOutAllocateOrderId(allocateOrderSDO.getOutAllocateOrderId());
        if (Objects.nonNull(allocateOrderSDO.getRemark())) {
            request.setRemark(allocateOrderSDO.getRemark());
        }
        request.setModifier(allocateOrderSDO.getUpdater());
        List<AllocateOrderDetailMessageSDO> allocateOrderDetailSDOS = messageSDO.getAllocateOrderDetailSDOS();
        if (CollectionUtils.isNotEmpty(allocateOrderDetailSDOS)) {
            List list = new ArrayList();
            for (AllocateOrderDetailMessageSDO allocateOrderDetailSDO : allocateOrderDetailSDOS) {
                AllocateOrderDetailUpdateSDO updateSDO = new AllocateOrderDetailUpdateSDO();
                updateSDO.setOutAllocateOrderLineId(allocateOrderDetailSDO.getOutAllocateOrderLineId());
                updateSDO.setRemark(allocateOrderDetailSDO.getRemarks());
                if (Boolean.TRUE.equals(allocateOrderDetailSDO.getClose())) {
                    updateSDO.setIsClosed("1");
                } else {
                    updateSDO.setIsClosed("0");
                }
                SimpleDateFormat format = new SimpleDateFormat(pattern);
                updateSDO.setModifyTime(format.format(new Date()));
                list.add(updateSDO);
            }
            request.setItems(list);
        }
        JSONObject messageHeader = new JSONObject();
        String messageId = UUID.randomUUID().toString();
        messageHeader.put("messageId", messageId);
        request.setMessageHeader(messageHeader);

        saveLog(request, messageId);
        log.info("MnSapIf037V2Service_doHandler_callSAP,request:{}", JSON.toJSONString(request));
        Object result = sapService.restSapAllocateOrderModify(request);
        log.info("MnSapIf037V2Service_doHandler,result:{}", JSON.toJSONString(result));
        return result;
    }

    private void saveLog(RestSapAllocateOrderModifyRequest request, String messageId) {
        try {
            SapRetry sapRetry = new SapRetry();
            sapRetry.setApiCode(API_CODE);
            sapRetry.setMessageId(messageId);
            sapRetry.setRetryTimes(0);
            sapRetry.setRequestTime(DateUtils.toDateStr(new Date(), DateUtils.DATETIME_FORMAT));
            sapRetry.setOutKey(request.getOutAllocateOrderId());
            sapRetry.setPriority(0);
            sapRetry.setParam(JSON.toJSONString(request));
            sapRetry.setStatus(RetryStatus.SUCCESS.getValue());
            sapRetryService.create(sapRetry);
        } catch (Exception e) {
            log.error("MnSapIf037V2Service saveLog error request=" + JSON.toJSONString(request), e);
        }
    }

    /**
     * callback
     *
     * @param callbackRequest
     */
    @Override
    public Object callback(CallbackRequest callbackRequest) {
        log.info("MnSapIf037V2Service_callback request={}", JSON.toJSONString(callbackRequest));
        try {
            JSONObject message = JSONObject.parseObject(callbackRequest.getMessage());
            JSONObject json = (JSONObject)message.getJSONArray("data").get(0);
            List<String> retryMsgs = Lists.newArrayList("用户");

            // 查询调用记录
            SapRetry sapRetry = null;
            String messageId = message.getJSONObject("MessageHeader").getString("MESSAGEID");
            if (StringUtils.isNotBlank(messageId)) {
                SapRetryLoadListRequest request = new SapRetryLoadListRequest();
                request.setMessageId(messageId);
                log.info("MnSapIf037V2Service_callback loadList request={}", JSON.toJSONString(request));
                Result<List<SapRetry>> loadResult = sapRetryService.loadList(request);
                log.info("MnSapIf037V2Service_callback loadList result={}", JSON.toJSONString(loadResult));
                if (CollectionUtils.isNotEmpty(loadResult.getResult())) {
                    sapRetry = loadResult.getResult().get(0);
                }
            }
            if (sapRetry != null) {
                if ("E".equals(json.getString("STATUS")) && json.getString("MESSAGE") != null && retryMsgs.stream()
                    .anyMatch(r -> json.getString("MESSAGE").contains(r))) {
                    // 更新调用记录为失败状态，后续自动重试
                    sapRetry.setStatus(RetryStatus.FAIL.getValue());
                    log.info("MnSapIf037V2Service_callback update request={}", JSON.toJSONString(sapRetry));
                    UpdateResponse response = sapRetryService.update(sapRetry);
                    log.info("MnSapIf037V2Service_callback update result={}", JSON.toJSONString(response));
                } else {
                    // 删除调用记录，记录用不着了
                    deleteRetry(sapRetry);
                }
            }
        } catch (Exception e) {
            log.error("MnSapIf037V2Service_callback error ", e);
        }
        return null;
    }

    private void deleteRetry(SapRetry sapRetry) {
        DeleteRequest request = new DeleteRequest();
        request.setId(sapRetry.getId());
        log.info("MnSapIf037V2Service_callback delete request={}", JSON.toJSONString(request));
        DeleteResponse response = sapRetryService.delete(request);
        log.info("MnSapIf037V2Service_callback delete result={}", JSON.toJSONString(response));
    }

    /**
     * autoRetry
     *
     * @param autoRetryRequest
     */
    @Override
    public Object autoRetry(AutoRetryRequest autoRetryRequest) {
        // 查询执行失败的记录
        SapRetryLoadListRequest request = new SapRetryLoadListRequest();
        request.setApiCode(API_CODE);
        request.setStatus(RetryStatus.FAIL.getValue());
        request.setLimit(100);
        request.setSize(100);
        log.info("MnSapIf037V2Service_autoRetry loadList request={}", JSON.toJSONString(request));
        Result<List<SapRetry>> loadResult = sapRetryService.loadList(request);
        log.info("MnSapIf037V2Service_autoRetry loadList result={}", JSON.toJSONString(loadResult));
        if (CollectionUtils.isEmpty(loadResult.getResult())) {
            return null;
        }
        for (SapRetry sapRetry : loadResult.getResult()) {
            // 重试达到一定次数的记录删除掉，继续重试也不一定会成功
            if (autoRetryRequest.getAutoDelete() && sapRetry.getRetryTimes() >= autoRetryRequest.getLimitRetryNum()) {
                log.info("MnSapIf037V2Service_autoRetry retryNum is {} limitNum={}",
                    autoRetryRequest.getLimitRetryNum(), autoRetryRequest.getLimitRetryNum());
                deleteRetry(sapRetry);
                continue;
            }
            // 执行重试，重新调用037
            RestSapAllocateOrderModifyRequest modifyRequest = JSON.parseObject(sapRetry.getParam(), RestSapAllocateOrderModifyRequest.class);
            log.info("MnSapIf037V2Service_autoRetry retry request:{}", JSON.toJSONString(modifyRequest));
            Object result = sapService.restSapAllocateOrderModify(modifyRequest);
            log.info("MnSapIf037V2Service_autoRetry retry result:{}", JSON.toJSONString(result));

            // 更新执行状态为已成功，如果还是失败，callback会更新状态
            sapRetry.setStatus(RetryStatus.SUCCESS.getValue());
            sapRetry.setRetryTimes(sapRetry.getRetryTimes() + 1);
            log.info("MnSapIf037V2Service_autoRetry update request={}", JSON.toJSONString(sapRetry));
            UpdateResponse response = sapRetryService.update(sapRetry);
            log.info("MnSapIf037V2Service_autoRetry update result={}", JSON.toJSONString(response));
            return result;
        }
        return null;
    }
}



/*
{
    "MessageHeader": {
    "MESSAGEID": "9f21da253aca41eaafe253dd8592e5cc",
    "INTERFACE": "SI_ZT_AllocateOrder_CHANGE_Asyn_OUT",
    "SENDER": "ECC",
    "SENDTIME": "2024-04-24 11:21:37",
    "RECEIVER": "YWZT"
    },
    "data": [
    {
    "HeaderKey": "9f21da253aca41eaafe253dd8592e5cc",
    "STATUS": "E",
    "MESSAGE": "用户0125983已经处理采购订单 4860807819",
    "SAPHeaderKey": 4860807819
    }
    ]
    }*/


/*{
    "MessageHeader": {
    "MESSAGEID": "9f21da253aca41eaafe253dd8592e5cc",
    "INTERFACE": "SI_ZT_AllocateOrder_CHANGE_Asyn_OUT",
    "SENDER": "ECC",
    "SENDTIME": "2024-04-24 11:21:37",
    "RECEIVER": "YWZT"
    },
    "data": [
    {
    "HeaderKey": "9f21da253aca41eaafe253dd8592e5cc",
    "STATUS": "E",
    "MESSAGE": "用户0125983已经处理采购订单 4860807819",
    "SAPHeaderKey": 4860807819
    }
    ]
    }*/
